<template>
  <div class="select_box">
    <div v-if="mode == 'select'">
      <el-select v-model="selectValue" :multiple="multiple" :placeholder="placeholder" :size="size"
        :style="`width: ${width}px`" @change="handleChange">
        <el-option v-for="(item, index) in selectData" :key="index" :label="item[labelKey]" :value="item[valueKey]">
          <span class="flex justify-between align-center">
            <span> {{ item[labelKey] }}</span>
            <span v-if="showField"> {{ item[showField] }}</span>
          </span>
        </el-option>
      </el-select>
    </div>

    <div v-if="mode === 'tree-select'">
      <el-tree-select v-model="selectValue" check-strictly :placeholder="placeholder" :data="selectData"
        :multiple="multiple" :render-after-expand="false" :size="size" @change="handleChange"
        :style="`width: ${width}px`" />
    </div>

    <div v-if="mode === 'api'">
      <el-select v-model="selectValue" @change="handleChange" :multiple="multiple" :placeholder="placeholder"
        :size="size" :style="{
          width: !isNoSetWidth && `${width}px`
        }">
        <el-option v-for="(item, index) in selectData" :key="index" :label="item[labelKey]" :value="item[valueKey]">
          <div class="flex justify-between">
            <span>
              <span :class="{ 'margin-left-xs': isLevele & item.level > 0 }"></span>
              {{ item[labelKey] }}
            </span>
            <!-- <el-tag>{{ item.level + 1 }}级</el-tag> -->
          </div>
        </el-option>
      </el-select>
    </div>

    <div v-if="mode === 'api-tree'">
      <el-tree-select v-model="selectValue" :placeholder="placeholder" :data="selectData" :multiple="multiple"
        :render-after-expand="false" size="large" @change="handleChange" :style="`width: ${width}px`"
        :label="labelKey" />
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref, toRef, watch, computed, onMounted } from 'vue'
import request from '@/api/request'

const props = defineProps({
  isNoSetWidth: {
    type: Boolean,
    default: false
  },

  size: {
    type: String,
    default: 'large'
  },

  showField: {
    type: String,
    default: ''
  },

  isLevele: {
    type: Boolean,
    default: false
  },

  isFlat: {
    type: Boolean,
    default: false
  },

  width: {
    type: [String, Number],
    default: '240'
  },

  mode: {
    type: String,
    default: 'select',
  },

  multiple: {
    type: Boolean,
    default: false,
  },

  placeholder: {
    type: String,
    default: '请选择',
  },

  data: {
    type: Array,
    default: () => [],
  },

  modelValue: {
    type: [String, Number],
    default: '',
  },

  labelKey: {
    type: String,
    default: 'label',
  },

  valueKey: {
    type: String,
    default: 'value',
  },

  apiUrl: {
    type: String,
    default: '',
  },

  params: {
    type: Object,
    default: () => ({})
  }
})

const selectValue = ref('')

const apiData = ref([])

const selectData = computed(() => {
  if (props.mode === 'api' || props.mode === 'api-tree') {
    return apiData.value
  } else {
    return props.data
  }
})

watch(selectValue, (newVal) => {
  let value = ''

  let isArrary = Array.isArray(newVal)

  if (isArrary) {
    value = newVal.join('|')
  } else {
    value = newVal
  }



  emit('update:modelValue', value)
}, {
  deep: true,
})

watch(
  () => props.modelValue,
  (newVal) => {
    selectValue.value = newVal
  },
  {
    deep: true,
    immediate: true
  }
)

const emit = defineEmits(['update:modelValue', 'change'])

const handleChange = () => {
  emit('change')
}

const getApiDataRequest = async () => {
  try {
    const res = await request({
      url: props.apiUrl,
      method: 'post',
      params: props.params,
    })

    if (props.isFlat) {
      apiData.value = flattenArrayWithLevel(res.data)
    } else {
      apiData.value = res.data
    }
  } catch (err) {
    console.log('getApiDataRequest', err)
  }
}

// 方法 1: 使用递归和 Children.forEach
function flattenArrayWithLevel(arr, level = 0) {
  return arr.reduce((acc, item) => {
    const { children, ...rest } = item;
    // 添加当前节点及其层级信息
    acc.push({ ...rest, level });

    // 递归处理子节点，并增加层级
    if (children && children.length > 0) {
      return acc.concat(flattenArrayWithLevel(children, level + 1));
    }

    return acc;
  }, []);
}

onMounted(() => {
  if (props.mode === 'api' || props.mode === 'api-tree') {
    getApiDataRequest()
  }
})
</script>

<style lang="scss" scoped></style>
